package top.ajunnihao.core.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * TODO 每日任务管理器(多线程)
 *
 * @author AJun
 * @version 1.0.0
 * @date 2020/5/31
 */
@Component
public class DailyTaskManager extends Thread {

    /**
     * 日志记录
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(DailyTaskManager.class);

    /**
     * 任务链表
     */
    private final List<TaskInfo> taskList = new ArrayList<TaskInfo>();

    /**
     * 线程退出标识
     */
    private boolean quitFlag = false;

    /**
     * 启动线程
     */
    public void doStart() {
        this.start();
    }

    /**
     * 停止线程
     */
    public void doQuit() {
        // 停止标志位置为 true
        this.quitFlag = true;
        // 打断睡眠的线程
        this.interrupt();
    }

    /**
     * 添加任务
     *
     * @param task 任务类
     * @param name 任务名称
     */
    public void addTask(Task task, String name) {
        TaskInfo taskInfo = new TaskInfo();
        taskInfo.task = task;
        taskInfo.name = name;
        taskList.add(taskInfo);
    }

    @Override
    public void run() {
        while (!this.quitFlag) {
            try {
                // 10 秒后执行任务
                Thread.sleep(10 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 执行任务
            for (TaskInfo taskInfo : this.taskList) {
                executeEveryDay(taskInfo);
            }
        }
    }

    /**
     * 每天执行任务
     *
     * @param info 任务信息
     */
    private void executeEveryDay(TaskInfo info) {
        // 获取当前时间
        Calendar instance = Calendar.getInstance();
        int today = instance.get(Calendar.DAY_OF_YEAR);
        if (today == info.lastValue) {
            // 今日任务已完成
            return;
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 执行任务
        try {
            LOGGER.info("** 执行定期任务 => [{}]: Start; 开始时间: {}", info.name, sdf.format(new Date()));
            info.task.execute(); // 执行任务
            info.status = 0; // 执行成功标识为 0
            LOGGER.info("** 执行定期任务 => [{}]: Success; 结束时间(成功): {}", info.name, sdf.format(new Date()));
        } catch (Exception e) {
            String reason = e.getMessage();
            if (reason == null) {
                reason = e.getClass().getName();
            }
            LOGGER.info("** 执行定期任务 => [{}]: Failure: {}; 结束时间(失败): {}", info.name, reason, sdf.format(new Date()));
            info.status = -1;
            e.printStackTrace();
        }

        // 设置任务执行完毕的时间
        info.lastValue = today;
        info.lastTime = instance.getTimeInMillis();
    }

    /**
     * 任务信息
     */
    private static class TaskInfo {
        Task task; // 任务
        String name = ""; // 任务名称
        int status = 0; // 执行成功，还是失败
        long lastTime = 0; // 任务执行完毕的时间(时间戳)
        int lastValue = -1; // 任务执行完毕的时间(第几天)
        int fromHour = -1; // [未用到] 开始时间点
        int toHour = -1; // [未用到] 结束时间点
        int numRetry = 0; // [未用到] 错误重试次数
    }

}
